<script setup lang="ts" generic="T extends Record<string, unknown>, K = never">
import { VueDraggable } from 'vue-draggable-plus';
import type { DataTableColumn } from 'naive-ui';
import { fetchColumnSetting, fetchAddColumnSetting } from "@/service/api/sys/setting"
import { ColumnKey} from 'naive-ui/es/data-table/src/interface';
import { BusinessStatus } from '~/src/enum';
import { isBusinessYse } from '~/src/utils/common';
import { useRouter } from 'vue-router';
import { onBeforeMount, ref, watch } from 'vue';

defineOptions({
  name: 'TableColumnSetting'
});

type Column = DataTableColumn<any>;
type EditColumn = Column & { key?: ColumnKey; title: string; } & Common.ColumnSetting;
const router = useRouter();
const fullPath: string = router.currentRoute.value.fullPath
const editColumns = ref<EditColumn[]>();
  interface Props {
  columns: Column[];
}

const { columns } = defineProps<Props>();
interface Emits {
  (e: 'update:columns', columns: Column[]): void;
}

const emit = defineEmits<Emits>();


function initList(): EditColumn[] {
  return columns.map((item:Column) => ({
    //@ts-ignore
    ...item, name: item.title as string, title: item.title,
    id: undefined, path: fullPath, visible: BusinessStatus.Yes, sort: 0, width: undefined
  }));
}

async function init() {
  let curList = initList()

  await handleColumnSetting(curList)
  editColumns.value = curList;
}
async function handleColumnSetting(curList: EditColumn[]) {
  const { data } = await fetchColumnSetting(fullPath)
  if (data && data.length > 0) {
    // 填充后台数据
    let before: boolean = true
    curList.forEach(it => {
      const key = it.key as string
      const temp = data.find((it: EditColumn) => it.name == key)
      it.name = key
      if (temp) {
        before = false;
        it.id = temp.id
        it.visible = temp.visible
        it.sort = temp.sort
        it.width = temp.width ? temp.width : it.width
      } else if(!key){
        it.visible = BusinessStatus.No
        it.sort = before ? -1 : 999
      }else{
        it.visible = BusinessStatus.Yes
      }
    })
    // 排序
    curList.sort((a, b) => a.sort - b.sort)
  }

}

function handleTrigger(e: boolean) {
  if (!e) {
    saveSetting()
  }
}
async function saveSetting() {
  const listVal = editColumns.value!
  listVal.forEach((it, i) => { it.sort = i; it.name = it.key as string })
  await fetchAddColumnSetting(listVal)
  await handleColumnSetting(listVal)
  editColumns.value = listVal;
}

watch(
  editColumns,
  newValue => {
    const newColumns = newValue!.filter(item => isBusinessYse(item.visible) || !item.key);
    const columnsTemp: Column[] = newColumns.map(item => ({ ...item }))
    emit('update:columns', columnsTemp);
  },
  { deep: true }
);
onBeforeMount(() => {
  init()
})
</script>

<template>
  <NPopover placement="bottom-end" trigger="click" :on-update:show="handleTrigger">
    <template #trigger>
      <NButton>
        <template #icon>
          <icon-ant-design-setting-outlined class="text-icon" />
        </template>
        列设置
      </NButton>
    </template>
    <VueDraggable v-model="editColumns!" handle=".handleDrag">
        <div v-for="item in editColumns" :key="item.key" class="h-36px flex-y-center rd-4px" v-bind:class="item.key ? 'handleDrag  hover:(bg-primary bg-opacity-20) ' :'disabled  hover:(bg-gray bg-opacity-20)'">
          <icon-mdi-drag class="mr-8px cursor-move text-icon" />
          <NCheckbox v-model:checked="item.visible" :checked-value="BusinessStatus.Yes" :disabled="item.key == null || item.key == '' ? true : false"
            :unchecked-value="BusinessStatus.No">
            {{ item.title }}
          </NCheckbox>
        </div>
    </VueDraggable>
  </NPopover>
</template>

<style scoped>
.disabled{
  cursor: not-allowed;
}
</style>
